package com.bf.electroplating.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bf.electroplating.login.UserContext;
import com.bf.electroplating.mapper.PubSystemModuleMapper;
import com.bf.electroplating.pojo.dto.IdDTO;
import com.bf.electroplating.pojo.dto.function.ModuleDTO;
import com.bf.electroplating.pojo.entity.PubSystemModule;
import com.bf.electroplating.pojo.entity.SysFunction;
import com.bf.electroplating.pojo.vo.PageVO;
import com.bf.electroplating.pojo.vo.ResultVO;
import com.bf.electroplating.pojo.vo.function.ModuleVO;
import com.bf.electroplating.service.ISysFunctionService;
import com.bf.electroplating.service.PubSystemModuleService;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 15451
* @description 针对表【pub_system_module(菜单表)】的数据库操作Service实现
* @createDate 2025-05-09 11:11:32
*/
@Service
public class PubSystemModuleServiceImpl extends ServiceImpl<PubSystemModuleMapper, PubSystemModule>
    implements PubSystemModuleService{

    @Resource
    private ISysFunctionService sysFunctionService;

    @Override
    public ResultVO<List<ModuleVO>> getSelectList() {
        List<ModuleVO> topList = new ArrayList<>();
        ModuleVO top = new ModuleVO();
        top.setFmainalias("顶层");
        top.setId("0");

        List<PubSystemModule> moduleList = list(new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, "0"));
        List<ModuleVO> moduleVOList = new ArrayList<>();
        moduleList.forEach(i -> {
            ModuleVO moduleVO = new ModuleVO();
            BeanUtils.copyProperties(i, moduleVO);
            moduleVO.setChildren(getAllChildren(i.getId()));
            moduleVOList.add(moduleVO);
        });

        //只保留functionVOS两层递归的数据
        moduleVOList.forEach(i -> {
            if (!i.getChildren().isEmpty()) {
                i.getChildren().forEach(j -> j.getChildren().clear());
            }
        });

        top.setChildren(moduleVOList);
        topList.add(top);
        return ResultVO.ok(topList);
    }

    @Override
    public ResultVO<Page<ModuleVO>> getPage(PageVO dto) {
        Page<PubSystemModule> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        Page<PubSystemModule> moduleVOList = page(page, new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, "0")
                .orderByAsc(PubSystemModule::getSortNum));

        Page<ModuleVO> moduleVOPage = new Page<>();
        BeanUtils.copyProperties(moduleVOList, moduleVOPage);
        List<ModuleVO> moduleList = new ArrayList<>();
        moduleVOList.getRecords().forEach(i -> {
            ModuleVO moduleVO = new ModuleVO();
            BeanUtils.copyProperties(i, moduleVO);
            moduleVO.setChildren(getAllChildren(i.getId()));
            moduleList.add(moduleVO);
        });

        moduleVOPage.setRecords(moduleList);
        return ResultVO.ok(moduleVOPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVO<Object> updateOrSave(ModuleDTO dto) {
        if (dto.getParentCode().size() > 3) {
            return ResultVO.fail(null, "最多支持三级菜单");
        }
        PubSystemModule pubSystemModule = new PubSystemModule();
        BeanUtils.copyProperties(dto, pubSystemModule);
        if (!dto.getParentCode().isEmpty()) {
            pubSystemModule.setFsuperid(dto.getParentCode().get(dto.getParentCode().size() - 1));
        }
        saveOrUpdate(pubSystemModule);
        SysFunction sysFunction = new SysFunction();
        sysFunction.setId(pubSystemModule.getId());
        sysFunction.setFunctionCode(pubSystemModule.getId());
        sysFunction.setFunctionName(pubSystemModule.getFmainalias());
        sysFunction.setParentCode(pubSystemModule.getFsuperid());
        sysFunction.setSort(pubSystemModule.getSortNum());
        sysFunctionService.saveOrUpdate(sysFunction);

        return ResultVO.ok(null, "操作成功");
    }

    @Override
    public ResultVO<Object> delete(IdDTO dto) {
        removeChildren(dto.getId());
        removeById(dto.getId());
        return ResultVO.ok(null, "删除成功");
    }

    private void removeChildren(String pid) {
        list(new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, pid))
                .forEach(i -> {
                    removeChildren(i.getId());
                    removeById(i.getId());
                });
    }

    @Override
    public ResultVO<ModuleDTO> getDetail(IdDTO dto) {
        PubSystemModule PubSystemModule = getById(dto.getId());
        ModuleDTO moduleDTO = new ModuleDTO();
        BeanUtils.copyProperties(PubSystemModule, moduleDTO);
        List<String> parentCode = getParentCode(PubSystemModule.getId());
        Collections.reverse(parentCode);
        moduleDTO.setParentCode(parentCode);
        return ResultVO.ok(moduleDTO);
    }

    @Override
    public ResultVO<List<ModuleVO>> getMenu() {
        List<PubSystemModule> parentFunctionList = list(new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, "0").orderByAsc(PubSystemModule::getSortNum));
        List<ModuleVO> moduleList = new ArrayList<>();
        parentFunctionList.forEach(i -> {
            ModuleVO module = new ModuleVO();
            BeanUtils.copyProperties(i, module);
            List<ModuleVO> children = getChildren(i.getId());
            if (children.isEmpty()){
                return;
            }
            module.setChildren(children);
            moduleList.add(module);
        });
        //过滤出满足权限的菜单
        return ResultVO.ok(moduleList);
    }

    private List<ModuleVO> getChildren(String pid) {
        List<ModuleVO> modules = list(new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, pid)
                .orderByAsc(PubSystemModule::getSortNum))
                .stream().map(i -> {
                    ModuleVO moduleVO = new ModuleVO();
                    BeanUtils.copyProperties(i, moduleVO);
                    return moduleVO;
                }).collect(Collectors.toList());
        //children为空则是最底层菜单
        List<ModuleVO> nullModules = new ArrayList<>();
        //存放非底层或权限过滤后的菜单
        List<ModuleVO> filteredModules = new ArrayList<>();
        modules.forEach(i -> {
            List<ModuleVO> children = getChildren(i.getId());
            if (children.isEmpty()) {
                nullModules.add(i);
            } else {
                i.setChildren(children);
                filteredModules.add(i);
            }
        });
        if (!nullModules.isEmpty()) {
            //对最底层菜单进行权限过滤
            List<ModuleVO> collect = nullModules.stream()
                    .filter(moduleVO -> UserContext.getUser().getFunctionIds().stream().anyMatch(id -> id.equals(moduleVO.getId())))
                    .collect(Collectors.toList());
            filteredModules.addAll(collect);
        }
        return filteredModules;
    }

    private List<String> getParentCode(String id) {
        List<String> parentCodeList = new ArrayList<>();
        PubSystemModule pubSystemModule = getById(id);
        if (pubSystemModule != null) {
            parentCodeList.add(pubSystemModule.getFsuperid());
            parentCodeList.addAll(getParentCode(pubSystemModule.getFsuperid()));
        }
        return parentCodeList;
    }

    private List<ModuleVO> getAllChildren(String pid) {
        List<ModuleVO> modules = list(new LambdaQueryWrapper<PubSystemModule>()
                .eq(PubSystemModule::getFsuperid, pid)
                .orderByAsc(PubSystemModule::getSortNum))
                .stream().map(i -> {
                    ModuleVO moduleVO = new ModuleVO();
                    BeanUtils.copyProperties(i, moduleVO);
                    return moduleVO;
                }).collect(Collectors.toList());
        modules.forEach(i -> i.setChildren(getAllChildren(i.getId())));
        return modules;
    }

}




